<

新しい画面にデータを送信する

多くの場合、新しい画面に移動するだけでなく、 ただし、データも画面に渡します。 たとえば、次のような情報を渡したい場合があります。 タップされた項目。

覚えておいてください: 画面は単なるウィジェットです。 この例では、todo のリストを作成します。 Todo がタップされると、新しい画面 (ウィジェット) に移動します。 todo に関する情報を表示します。 このレシピでは次の手順を使用します。

  1. todoクラスを定義します。
  2. Todoのリストを表示します。
  3. Todoに関する情報を表示できる詳細画面を作成します。
  4. データを詳細画面に移動して渡します。

1. todoクラスを定義する

まず、todo を表す簡単な方法が必要です。この例では、 タイトルと説明という 2 つのデータを含むクラスを作成します。

class Todo {
  final String title;
  final String description;

  const Todo(this.title, this.description);
}

2. Todoリストを作成する

次に、todo のリストを表示します。この例では、 20 個の Todo をリストビューを使用して表示します。 リストの操作の詳細については、 を参照してくださいリストを使用するレシピ。

Todoリストを生成する

final todos = List.generate(
  20,
  (i) => Todo(
    'Todo $i',
    'A description of what needs to be done for Todo $i',
  ),
);

ListView を使用して Todo のリストを表示する

ListView.builder(
  itemCount: todos.length,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text(todos[index].title),
    );
  },
),

ここまでは順調ですね。 これにより 20 個の Todo が生成され、ListView に表示されます。

3. リストを表示するTodo画面を作成する

このために、StatelessWidget。私たちはそれをそう呼んでいますTodosScreen。 このページの内容は実行中に変更されないため、 リストを要求する必要があります このウィジェットの範囲内の todo の数。

私たちは、ListView.builder戻るウィジェットの本体としてbuild()。 これにより、リストが画面に表示されるので、すぐに始めることができます。

class TodosScreen extends StatelessWidget {
  // Requiring the list of todos.
  const TodosScreen({super.key, required this.todos});

  final List<Todo> todos;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Todos'),
      ),
      //passing in the ListView.builder
      body: ListView.builder(
        itemCount: todos.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text(todos[index].title),
          );
        },
      ),
    );
  }
}

Flutter のデフォルトのスタイルを使用すれば、苦労せずに作業を進めることができます。 後でやりたいこと!

4. Todoに関する情報を表示する詳細画面を作成する

次に、2番目の画面を作成します。画面のタイトルには、 todo のタイトル、画面の本文に説明が表示されます。

詳細画面は普通なのでStatelessWidget、 ユーザーに入力を要求するTodoUIで。 次に、指定された todo を使用して UI を構築します。

class DetailScreen extends StatelessWidget {
  // In the constructor, require a Todo.
  const DetailScreen({super.key, required this.todo});

  // Declare a field that holds the Todo.
  final Todo todo;

  @override
  Widget build(BuildContext context) {
    // Use the Todo to create the UI.
    return Scaffold(
      appBar: AppBar(
        title: Text(todo.title),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Text(todo.description),
      ),
    );
  }
}

5. 詳細画面に移動してデータを渡します

とともにDetailScreen所定の位置に、 ナビゲーションを実行する準備ができました。 この例では、次の場所に移動します。DetailScreenユーザーのとき リスト内の ToDo をタップします。 todo をに渡しますDetailScreen

ユーザーのタップをキャプチャするにはTodosScreen、書きますonTap()のコールバックListTileウィジェット。以内onTap()折り返し電話、 使用Navigator.push()方法。

body: ListView.builder(
  itemCount: todos.length,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text(todos[index].title),
      // When a user taps the ListTile, navigate to the DetailScreen.
      // Notice that you're not only creating a DetailScreen, you're
      // also passing the current todo through to it.
      onTap: () {
        Navigator.push(
          context,
          MaterialPageRoute(
            builder: (context) => DetailScreen(todo: todos[index]),
          ),
        );
      },
    );
  },
),

インタラクティブな例

import 'package:flutter/material.dart';

class Todo {
  final String title;
  final String description;

  const Todo(this.title, this.description);
}

void main() {
  runApp(
    MaterialApp(
      title: 'Passing Data',
      home: TodosScreen(
        todos: List.generate(
          20,
          (i) => Todo(
            'Todo $i',
            'A description of what needs to be done for Todo $i',
          ),
        ),
      ),
    ),
  );
}

class TodosScreen extends StatelessWidget {
  const TodosScreen({super.key, required this.todos});

  final List<Todo> todos;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Todos'),
      ),
      body: ListView.builder(
        itemCount: todos.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text(todos[index].title),
            // When a user taps the ListTile, navigate to the DetailScreen.
            // Notice that you're not only creating a DetailScreen, you're
            // also passing the current todo through to it.
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => DetailScreen(todo: todos[index]),
                ),
              );
            },
          );
        },
      ),
    );
  }
}

class DetailScreen extends StatelessWidget {
  // In the constructor, require a Todo.
  const DetailScreen({super.key, required this.todo});

  // Declare a field that holds the Todo.
  final Todo todo;

  @override
  Widget build(BuildContext context) {
    // Use the Todo to create the UI.
    return Scaffold(
      appBar: AppBar(
        title: Text(todo.title),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Text(todo.description),
      ),
    );
  }
}

または、RouteSettings を使用して引数を渡します

最初の 2 つの手順を繰り返します。

引数を抽出する詳細画面を作成する

次に、タイトルと説明文を抽出して表示する詳細画面を作成します。Todo。にアクセスするには、Todo、 使用ModalRoute.of()方法。このメソッドは、現在のルートを引数とともに返します。

class DetailScreen extends StatelessWidget {
  const DetailScreen({super.key});

  @override
  Widget build(BuildContext context) {
    final todo = ModalRoute.of(context)!.settings.arguments as Todo;

    // Use the Todo to create the UI.
    return Scaffold(
      appBar: AppBar(
        title: Text(todo.title),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Text(todo.description),
      ),
    );
  }
}

最後に、に移動しますDetailScreenユーザーがタップしたとき あるListTileウィジェットを使用してNavigator.push()。 の一部として引数を渡しますRouteSettings。 のDetailScreenこれらの引数を抽出します。

ListView.builder(
  itemCount: todos.length,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text(todos[index].title),
      // When a user taps the ListTile, navigate to the DetailScreen.
      // Notice that you're not only creating a DetailScreen, you're
      // also passing the current todo through to it.
      onTap: () {
        Navigator.push(
          context,
          MaterialPageRoute(
            builder: (context) => const DetailScreen(),
            // Pass the arguments as part of the RouteSettings. The
            // DetailScreen reads the arguments from these settings.
            settings: RouteSettings(
              arguments: todos[index],
            ),
          ),
        );
      },
    );
  },
)

完全な例

import 'package:flutter/material.dart';

class Todo {
  final String title;
  final String description;

  const Todo(this.title, this.description);
}

void main() {
  runApp(
    MaterialApp(
      title: 'Passing Data',
      home: TodosScreen(
        todos: List.generate(
          20,
          (i) => Todo(
            'Todo $i',
            'A description of what needs to be done for Todo $i',
          ),
        ),
      ),
    ),
  );
}

class TodosScreen extends StatelessWidget {
  const TodosScreen({super.key, required this.todos});

  final List<Todo> todos;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Todos'),
      ),
      body: ListView.builder(
        itemCount: todos.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text(todos[index].title),
            // When a user taps the ListTile, navigate to the DetailScreen.
            // Notice that you're not only creating a DetailScreen, you're
            // also passing the current todo through to it.
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => const DetailScreen(),
                  // Pass the arguments as part of the RouteSettings. The
                  // DetailScreen reads the arguments from these settings.
                  settings: RouteSettings(
                    arguments: todos[index],
                  ),
                ),
              );
            },
          );
        },
      ),
    );
  }
}

class DetailScreen extends StatelessWidget {
  const DetailScreen({super.key});

  @override
  Widget build(BuildContext context) {
    final todo = ModalRoute.of(context)!.settings.arguments as Todo;

    // Use the Todo to create the UI.
    return Scaffold(
      appBar: AppBar(
        title: Text(todo.title),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Text(todo.description),
      ),
    );
  }
}